#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/errno.h>


int creation_result;
int cancel_result;
int complete = 0;
char bufor[BUFSIZ];


/**
* This function print a message to the stdout
*
*/
void showErrorAndTerminate(char tekst[])
{
	printf("ERROR : %s !!!\n",tekst);
	exit(-1);
}


/**
* the thread can terminate in 3 different ways
* - the main program calls pthread_cancel
* - function pthread_exit() is called explicitely from within the thread
* - myroutine returns => implicit call to pthread_exit()
*/
void * myDownloadRoutine()
{

	printf("[thread] myDownloadRoutine() started - cancellation disabled.\n");


	//------------------------------------------------------------------------
	// Disable cancellation for a while, so that we don't immediately react to a cancellation request
	//------------------------------------------------------------------------
	int s;
	s = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
	if (s != 0)
		showErrorAndTerminate("pthread_setcancelstate");

	sleep(5);
	printf("[thread] myDownloadRoutine(): about to enable cancellation\n");

	s = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
	if (s != 0)
		showErrorAndTerminate("pthread_setcancelstate");
	//------------------------------------------------------------------------
	// Starting our fake download...
	//------------------------------------------------------------------------
	/* sleep() is a cancellation point */
	printf("[thread] myDownloadRoutine(): starting download!!!\n");
	int i = 0;
	for (i=0;i<30;i++){
		printf("*");// Note: we don't put the newline character...
		fflush(stdout);//we must force printing to stdout because we don't use newline char
		sleep(1);
	}	
	printf("\n");
	//we set the flag to complete
	complete = 1;
	printf("[thread] myDownloadRoutine(): download complete!!!\n");
	pthread_exit(0);
}//myDownloadRoutine

int main(){

	printf("\n");
	printf("[Main] Program starting...\n");
	printf("\n");
	printf("Press RETURN at anytime to cancel the download : \n");
	printf("\n");
	printf("\n");
	pthread_t thread_handle;//this is a buffer for the thread handle
	//---------------------------------------------------	
	//1. ready to create a thread
	//---------------------------------------------------	
	pthread_attr_t attr;
	if ( pthread_attr_init ( &attr ) == 0  && pthread_attr_setdetachstate ( &attr , PTHREAD_CREATE_DETACHED ) == 0) {
		printf("[system] calling the function PTHREAD_CREATE ...\n");
		creation_result = pthread_create(&thread_handle, &attr, myDownloadRoutine, NULL);
		if (creation_result != 0) showErrorAndTerminate("PORAZKA\n");

	sleep(2);           /* Give thread a chance to get started */
	}	
	//---------------------------------------------------	
	//2. Allow the user to cancel the background thread
	//---------------------------------------------------	
	char bufor[BUFSIZ];
	//reading from standard input	

	fgets(bufor,BUFSIZ,stdin);    
	
	//---------------------------------------------------	
	//3. Cancelling the background thread
	//---------------------------------------------------	
	if ( complete == 0)
	{	
		printf("[system] sending cancellation request...\n");
		cancel_result = pthread_cancel(thread_handle);

		if (cancel_result != 0) showErrorAndTerminate("PORAZKA\n");
	}
	//---------------------------------------------------	
	//4. Exiting...
	//---------------------------------------------------	
	printf("[Program] Exiting...\n");
	exit(0);

}//main
